#include "Characters/Character.h"
#include "../Utils/FileUtils.h"
#include "../Utils/DataUtils.h"
#include "../Utils/AssertUtils.h"

CCharacter::CCharacter(CharacterType::Enum type)
: CObject(ObjectType::Character)
, m_eCharacterType(type)
, m_iMana(0)
, m_iMaxMana(0)
, m_iSkillCost(0)
, m_fMovementSpeed(0)
, m_fManaTimer(0)
, m_fMaxCameraHeight(0)
, m_fSecondsPerManaRate(0)
, m_bIsControllable(true)
, m_bIsManaCharging(true)
, m_pStateMachine(nullptr)
{
	LoadDataFile();
	m_pStateMachine = new CStateMachine<CCharacter>(this);
}

CCharacter::~CCharacter()
{
	delete m_pStateMachine;
	m_pStateMachine = nullptr;
}

void CCharacter::LoadDataFile()
{
	std::string charFilePath = "Resources/Characters/" + CharacterType::StringForEnum[m_eCharacterType] + ".json";
	Json::Value root = FileUtils::ParseJsonFromFile(charFilePath);

	if (root.empty())
	{
		DebugAssert(false, "Unable to read character file");
		return;
	}

	const std::string kManaStr = "mana";
	const std::string kMovementSpeedStr = "movement_speed";
	const std::string kSecondsPerManaStr = "seconds_per_mana_point";
	const std::string kMaxCameraHeightStr = "max_camera_height";
	const std::string kSkillCostStr = "skill_cost";
	const std::string kSkillDescStr = "skill_description";
	const std::string kSkillNameStr = "skill_name";

	std::string arr[] =
	{
		kManaStr,
		kMovementSpeedStr,
		kSecondsPerManaStr,
		kMaxCameraHeightStr,
		kSkillCostStr,
		kSkillDescStr,
		kSkillNameStr
	};

	for (int i = 0; i < sizeOfArray(arr); ++i)
	{
		DebugAssert(root.isMember(arr[i]), "Missing variable type: %s", arr[i].c_str());
	}

	m_iMaxMana = root[kManaStr].asInt();
	m_fSecondsPerManaRate = (float)root[kSecondsPerManaStr].asDouble();
	m_fMovementSpeed = (float)root[kMovementSpeedStr].asDouble();
	m_iSkillCost = root[kSkillCostStr].asInt();
	m_tSkillDesc = root[kSkillDescStr].asString();
	m_tSkillName = root[kSkillNameStr].asString();
	m_fMaxCameraHeight = (float)root[kMaxCameraHeightStr].asDouble();

	Log::Debug("%s loaded!", root["character"].asCString());
}

void CCharacter::MoveLeft(float dt)
{
	DoMoveLeft(dt);
}

void CCharacter::MoveRight(float dt)
{
	DoMoveRight(dt);
}

void CCharacter::MoveUp(float dt)
{
	DoMoveUp(dt);
}

void CCharacter::MoveDown(float dt)
{
	DoMoveDown(dt);
}

void CCharacter::UseSkill()
{
	DoUseSkill();
}

void CCharacter::Update(float dt)
{
	m_pStateMachine->Update(dt);

	if (m_bIsManaCharging)
	{
		m_fManaTimer -= dt;
		if (m_iMana < m_iMaxMana && m_fManaTimer < 0.0f)
		{
			m_fManaTimer = m_fSecondsPerManaRate;
			m_iMana++;
		}
	}

	DoUpdate(dt);
}

int CCharacter::GetMana() const
{
	return m_iMana;
}

int CCharacter::GetSkillCost() const
{
	return m_iSkillCost;
}

bool CCharacter::GetIsControllable() const
{
	return m_bIsControllable;
}

float CCharacter::GetMovementSpeed() const
{
	return m_fMovementSpeed;
}

float CCharacter::GetMaxCameraHeight() const
{
	return m_fMaxCameraHeight;
}

const std::string& CCharacter::GetSkillName() const
{
	return m_tSkillName;
}

const std::string& CCharacter::GetSkillDesc() const
{
	return m_tSkillDesc;
}

CharacterType::Enum CCharacter::GetCharacterType()
{
	return m_eCharacterType;
}
